package com.zh.netty.nio.groupchat;



import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;

/**
 * 群聊系统服务端
 */
public class GroupChatServer {
    // 定义属性
    private Selector selector;
    private ServerSocketChannel listenerChannel; // 监听

    // 初始化
    private static final int POET = 6667; // 端口

    public GroupChatServer(){
        try {
            //  得到选择器
            selector = Selector.open();
            // 初始化ServerSocketChannel
            listenerChannel = ServerSocketChannel.open();
            // 绑定端口
            listenerChannel.socket().bind(new InetSocketAddress(POET));
            // 设置非阻塞模式
            listenerChannel.configureBlocking(false);
            // 将 listenerChannel 注册到selector
            listenerChannel.register(selector, SelectionKey.OP_ACCEPT);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    // 监听
    public void listener(){
        try {
            // 循环处理
            while (true){
                int count = selector.select();
                System.out.println("count===="+count);
                if (count > 0){  // 有事件要处理
                    // 遍历得到的selectionKey 集合
                    selector.selectedKeys().forEach(key -> {
                        // 判断监听到的事件

                        //监听到accept
                        if(key.isAcceptable()){
                            try {
                                SocketChannel socketChannel = listenerChannel.accept();
                                // 设置为非阻塞
                                socketChannel.configureBlocking(false);
                                // 将socketChannel 注册到selector
                                socketChannel.register(selector, SelectionKey.OP_READ);
                                // 提示上线
                                System.out.println(socketChannel.getRemoteAddress()+" 上线");
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }else if (key.isReadable()){ // 通道发生读事件
                            //处理读
                            readData(key);
                        }

                        // 将当前的key 删除，放在重复处理
                        selector.selectedKeys().remove(key);
                    });

                }else {
                    System.out.println("============等待============");
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {

        }
    }

    // 读取客户端消息
    private void readData(SelectionKey key){
        // 定义一个SocketChannel
        SocketChannel channel = null;
        try {
            // 渠道关联的channel
            channel = (SocketChannel) key.channel();

            // 创建缓冲buffer
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            // 读取数据到buffer
            int count = channel.read(byteBuffer);
            // 根据count 的值做处理
            if(count > 0){  // 读取到数据
                // 将缓冲区的数据转化成字符串
                String msg = new String(byteBuffer.array());
                // 输出该消息
                System.out.println("from 客户端："+ msg);

                // 想其他客户端转发消息
                sendMsgByClient(msg,channel);
            }
        }catch (IOException e){
            try {
                System.out.println(channel.getRemoteAddress() +"离线");
                // 取消注册
                key.cancel();
                // 关闭通道
                channel.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

    // 转发消息给其他客户端,socketChannel是自己，需要排除自己
    private void sendMsgByClient(String msg, SocketChannel socketChannel) throws IOException {
        System.out.println("服务器转发消息中");
        // 遍历所有注册到Selector上的SocketChannel，并排除自己
        for (SelectionKey key : selector.keys()) {

            // 通过key ,获取对应的SocketChannel
            Channel channel = key.channel();

            // 判断排除自己
            if(channel instanceof  SocketChannel && channel != socketChannel){
                SocketChannel dest = (SocketChannel) channel;
                // 将msg 存储到buffer
                ByteBuffer byteBuffer = ByteBuffer.wrap(msg.getBytes());

                // 将 buffer的数据写入到通道
                dest.write(byteBuffer);
            }
        }
    }

    public static void main(String[] args) {
        // 创建一个服务器对象
        GroupChatServer groupChatServer = new GroupChatServer();
        // 监听
        groupChatServer.listener();
    }

}
